<?php


/**
 * this class provides functions for uploading, downloading 
 * @author		ungerboeck simon <su@militaerversand.at>
 *
 */
class Filestore {
	private $response;
	private $createdIds;

	/**************************************************************************
	 **************************** PUBLIC FUNCTIONS ****************************
	 **************************************************************************/


	public function __construct() {
		$this->response = new ResponseInfo();
		$this->createdIds = array();
	}


	/**
	 * uploads one or more files and create db entries for this files
	 * @param		string		$path
	 * @param		boolean		$encrypt
	 * 
	 */
	public function upload($path, $encrypt = false) {
		//TODO encrypt content
		foreach ($_FILES as $fileInfos) {
			$fileInfos = $this->transformInfo($fileInfos);

			$i = 0;
			foreach ($fileInfos as $fileInfo) {
				if (is_uploaded_file($fileInfo["tmp_name"])) {
					$extension = pathinfo($fileInfo["name"], PATHINFO_EXTENSION);
					$filename = pathinfo($fileInfo["name"], PATHINFO_FILENAME);
					$tempname = $fileInfo["tmp_name"];
					$size = $fileInfo['size'];
					$physicalname = md5(microtime(true) . $i);	//$i is an idendifier if two or more files has the same microtimestamp
					
					if ($this->moveFile($physicalname, $tempname, $path))
						$this->registerFile($filename, $extension, $physicalname, $size, $path, $encrypt);
				}
				$i++;
			}
		}

		$this->response->ids = $this->createdIds;
		return $this->createdIds;
	}
	
	
	/**
	 * downloads the file by given id or given object
	 * @param 		int|mixed		 $fileId
	 */
	public function download($file){
		if (is_numeric($file))
			$file = DataFile::find($file);
		
		if ($file != null)
			$this->downloadFile($file);	
	}
	
	
	/**
	 * deletes given file
	 * @param 		int|mixed		 $file
	 */
	public function delete($file){
		if (is_numeric($file))
			$file = DataFile::find($file);
		
		if ($file != null)
			return $this->deleteFile($file);
	}
	
	
	/**
	 * returns the response
	 * @return 		mixed		$this->response
	 */
	public function getResponse(){
		return $this->response;
	}


	/**************************************************************************
	 **************************** PRIVATE FUNCTIONS ***************************
	 **************************************************************************/
	
	/**
	 * deletes file from db, if that was successfull -> delete physical file
	 * @param 		mixed		 $file
	 */
	private function deleteFile($file){
		$success = true;
		try{
			$file->delete();
			$filename = $file->path . '/' . $file->physicalname;
			if (file_exists($filename))
				unlink($filename);
			else {
				$this->response->failed();
				$this->response->addMessage('File existiert nicht!');
				$success = false;
			}
		} catch(Exception $e){
			$this->response->failed();
			$this->response->addMessage('File konnte nicht gel&ouml;scht werden!');
			$success = false;
		}
		
		return $success;
	}
	
	
	
	
	/**
	 * downloads the given file
	 * @param 		mixed		 $file
	 */
	private function downloadFile($file){
		$shownFileName = $file->filename . '.' . $file->extension;
	//	header("Content-Type: " . $fileInfo['mimetype']);
		header("Content-Disposition: attachment; filename=\"" . $shownFileName . "\"");
		readfile($file->path . '/' . $file->physicalname);
	}
	


	/**
	 * the array structure of the $_FILES object is not good
	 * this functions transform the it in this structure
	 * 
	 * Array
	 *	(
	 *		[0] => Array
	 *	   (
	 *		       [name] => foo.txt
	 *		       [type] => text/plain
	 *		       [tmp_name] => /tmp/phpYzdqkD
	 *      	   [size] => 123
	 *	    )
	 *
	 *	   [1] => Array
	 *	   (
	 *		       [name] => bar.txt
	 *		       [type] => text/plain
	 *		       [tmp_name] => /tmp/phpeEwEWG
	 *		       [size] => 456
	 *	    )
	 *	)
	
	 * @param 		array	 $fileInfo
	 * @return 		array	 $files
	 */
	private function transformInfo($fileInfo) {
		$files = array();
		$count = count($fileInfo['name']);
		$keys = array_keys($fileInfo);

		for ($i = 0; $i < $count; $i++) {
			foreach ($keys as $key) {
				$files[$i][$key] = $fileInfo[$key][$i];
			}
		}

		return $files;
	}


	/**
	 * creates new
	 * @param 		string		 $filename
	 * @param 		string		 $extension
	 * @param		string		 $physicalname
	 * @param 		float		 $size
	 * @param 		string		 $path
	 * @param 		boolean		 $encrypt
	 */
	private function registerFile($filename, $extension, $physicalname, $size, $path, $encrypt) {
		$file = new DataFile();
		$file->filename = $filename;
		$file->path = $path;
		$file->extension = $extension;
		$file->size = $size;
		$file->isEncrypted = $encrypt;
		$file->physicalname = $physicalname;
		if (!$file->save()) {
			$this->response->failed();
			$this->response->addMessage('Fehler beim Anlegen der Datei \'' . $filename . '\'!');
		} else
			array_push($this->createdIds, $file->id);
	}


	/**
	 * moves the file to given direcotry
	 * @param               string          $filename
	 * @param              string          $tempname
	 * @param               string          $path
	 */
	private function moveFile($filename, $tempname, $path) {
		$success = false;

		if (!file_exists($path)) //create path directory if not exists
			mkdir($path);

		if (!file_exists($path . '/' . $filename)) {
			if (move_uploaded_file($tempname, $path . '/' . $filename))
				$success = true;
			else {
				$this->response->failed();
				$this->response->addMessage('File \'' . $filename . '\' konnte nicht ins Zielverzeichnis kopiert werden!');
			}
		} else {
			$this->response->failed();
			$this->response->addMessage('File \'' . $filename . '\' kann nicht hochgeladen werden. Filename existiert bereits!');
		}
		return $success;
	}


}